<?php
/**
 * Created by PhpStorm.
 * User: silentium
 * Date: Sep 16, 2010
 * Time: 1:25:23 AM
 * To change this template use File | Settings | File Templates.
 */


/**
 * Static class for interacting with MySQL database
 * using mysqli libraries for php
 *
 * @author silentium
 * @license GPLv2
 * @static
 * @global
 */
class MySQL {
  /**
   * MySQL server host
   * @staticvar string $host
   * MySQL server login
   * @staticvar string $user
   * MySQL server password
   * @staticvar string $pwd
   * MySQL database name
   * @staticvar string $db
   */
  public static $host, $user, $pwd, $db;
  /**
   * db queries counter
   * @staticvar int $count
   */
  public static $count=0;
  /**
   * MySQL connection resource
   * @staticvar mysqli $conn
   * MySQL error message
   * @staticvar string $error
   * last executed query
   * @staticvar $last
   */
  public static $conn, $error, $last;
  public static $log = array();

  /**
   * Connect to MySQL database
   * @return bool
   */
  public static function connect() {
    self::$conn = mysql_connect( self::$host, self::$user, self::$pwd );
    if ( $error = mysql_error() ) {
      if ( defined('DEBUG') ) {
        self::$log[] = $error;
      }
      return false;
    }
    return mysql_select_db(self::$db);
  }


  /**
   * close connection to the database
   * @return void
   */
  public static function close() {
    if ( is_resource( self::$conn ) ) {
      mysql_close( self::$conn );
      if (defined('DEBUG') && DEBUG) {
        echo "\n<!--\n";
        print_r(self::$log);
        echo "\n-->\n";
      }
    }
  }


  /**
   * Exectute query to the database
   * @param string $sql
   * @return MySQL_Result Query result
   */
  public static function q( $sql ) {
    // query parameters
    $keys = array();
    $vals = array();

    // inserting parameters into ::n
    $n = (func_num_args()-1)*2;
    foreach ( func_get_args() as $key => $val ) {
      if ( $key ) {
        // insert escaped value at ::$key
        $keys[--$n] = '::'.$key;
        $vals[$n] = addslashes($val);
        // insert integer value at :i$key
        $keys[--$n] = ':i'.$key;
        $vals[$n] = $val+0;
      }
    }
    $sql = str_replace( $keys, $vals, $sql );

    // split queries by delimiter (may be several queries)
    $sql = explode( ";;\n", $sql );
    self::$error = '';
    foreach ( $sql as $q ) {
      //execute query
      $res = mysql_query( $q, self::$conn );
      // save an error message for debug purposes
      self::$error .= mysql_error( self::$conn ) . "\n";
      // inc query counter
      ++self::$count;
    }
    if ( defined('DEBUG') ) {
      array_push( self::$log,
        array( $sql, ) );
      self::$error && array_push( self::$log, self::$error );
    }

    return new MySQL_Result( $res );
  }


  /**
   * wrapper for q($sql) method
   * @param string $sql
   * @return MySQL_Result Query result
   */
  public static function query( $sql ) {
    return self::q( $sql );
  }


  /**
   * identifier of last inserted row
   * @return int
   */
  public static function inserted() {
    return mysql_insert_id( self::$conn );
  }

  /**
   * Connection status. True if connected.
   * @return bool
   */
  public static function ok() {
    return is_resource( self::$conn );
  }


  /**
   * Connection status. True if connected.
   * @return bool
   */
    public static function connected() {
    return is_resource( self::$conn );
  }



  /**
   * Delete row by $id from $table
   * @param string $table
   * @param int $id
   * @return bool
   */
  public static function delete( $table, $id ) {
  	return self::q( "DELETE FROM `".$table."` WHERE `id`=':i1'", $id ) ;
  }


}




/**
 * MySQLi result handler class
 */
class MySQL_Result extends Vector {
  /**
   * Result resourse
   * @var Resource $res
   */
  private $res=false;
  /**
   * number of result rows
   * @var integer $num
   */
  private $num = 0;
  /**
   * cursor for rows
   * @var integer $cursor
   */
  private $cursor=0;
  /**
   * Cursor initiated flag
   * @var bool
   */
  private $init=false;

  /**
   * class constructor.
   * Determine query success. Fetch rows, if they exist.
   * @param mysql_result $res
   */
  public function __construct($res) {
    if ( is_resource( $res ) ) {
      for ( $this->num=0 ; $this->items[] = mysql_fetch_assoc($res); $this->num++ ) {}
      array_pop( $this->items );
      mysql_free_result($res);
    } elseif ( $res===true ) {
      $this->items = true;
    }
  }


  /**
   * wrapper for success() method. exists for compatibility.
   * @return bool
   */
  public function ready() {
    return $this->success();
  }

  /**
   * check if query succeeded
   * @return bool
   */
  public function success() {
    if ( $this->num || $this->items===true ) {
  	  return true;
  	} else {
  	  return false;
  	}
  }



  /**
   * check if row at cursor exists
   * @return bool
   */
  public function exists() {
    return $this->cursor < $this->num && $this->cursor >= 0;
  }



  /**
   * Return result rows count
   * @return int
   */
  public function num() {
    return $this->num;
  }


  /**
   * Return result row as numerated array
   * @return array
   */
  public function row() {
    $res = false;
    if ( $this->exists() ) {
      $res = array();
      foreach ( $this->items[$this->cursor] as &$val ) {
        $res[] = $val;
      }
    }
    ++$this->cursor;
    return $res;
  }


  /**
   * Return result row a associative array field => value
   * @return assoc_array
   */
  public function assoc() {
    if ( $this->exists() ) {
      return $this->items[$this->cursor++];
    } else {
      return false;
    }
  }


  /**
   * Return $field value of current row
   * @param string $field
   * @return mixed
   */
  public function get($field) {
    if ( $this->exists() ) {
      return $this->items[$this->cursor++][$field];
    }
    return false;
  }


  /**
   * Return values of $field as array
   * @param string $field
   * @return array
   */
  public function get_array($field) {
    if ( $this->num ) {
      $a = array();
      foreach ( $this->items as $res ) {
        $a[] = $res[$field];
      }
      return $a;
    } else {
      return false;
    }
  }


  /**
   * Return rows or values of $field as array
   * @param string[optional] $field
   * @return array
   */
    public function arr( $field=null ) {
    if ( $this->num ) {
      return $field ? $this->get_array($field) : $this->items;
    } else {
      return false;
    }
  }


  /**
   * Switch to the next row
   * @return MySQL_Result
   */
  public function next() {
    if ( $this->exists() ) {
      if ( !$this->init ) {
        $this->init = true;
        if ( $this->cursor===0 ) {
          return $this;
        }
      }
      ++$this->cursor;
    }
    return $this;
  }


  /**
   * Switch to the previous row
   * @return MySQL_Result
   */
  public function prev() {
    if ( $this->exists() ) {
      --$this->cursor;
    }
    return $this;
  }


  /**
   * Switch to the last row
   * @return MySQL_Result
   */
  public function last() {
    $this->cursor = $this->num-1;
    return $this;
  }


  /**
   * Switch to the first row
   * @return MySQL_Result
   */
  public function first() {
    !$this->init && $this->init = true;
    $this->cursor = 0;
    return $this;
  }


  /**
   * Switch to the initial row
   * @return MySQL_Result
   */
  public function initial() {
    $this->init = false;
    $this->cursor = 0;
    return $this;
  }


  public function __get( $name ) {
    !$this->init && $this->init = true;
    return $this->exists() ? $this->items[$this->cursor][$name] : null;
  }
  public function __set( $name, $value ) {
    !$this->init && $this->init = true;
    return $this->items[$this->cursor][$name] = $value;
  }

}

